Skip to content

http: emit 'drain' on OutgoingMessage only after buffers drain#62936

Open
ronag wants to merge 1 commit intonodejs:mainfrom
ronag:http-drain-writable-length
Open

http: emit 'drain' on OutgoingMessage only after buffers drain#62936
ronag wants to merge 1 commit intonodejs:mainfrom
ronag:http-drain-writable-length

Conversation

@ronag
Copy link
Copy Markdown
Member

@ronag ronag commented Apr 24, 2026

Previously, socketOnDrain could be invoked synchronously from _flushOutput (via _onPendingData -> updateOutgoingData) while the bytes just handed to the socket were still buffered and while outputSize had not yet been reset on the OutgoingMessage. The 'drain' event fired even though res.writableLength was non-zero, breaking the invariant a user would reasonably expect after while (!res.write(...));.

Gate the emission in socketOnDrain on msg.writableLength === 0 (which also covers outputSize + chunked buffer + socket.writableLength), and apply the same check in OutgoingMessage._flush so that 'drain' is only emitted when the response is genuinely drained. The socket's own 'drain' event will otherwise propagate through socketOnDrain when the socket buffer actually empties.

Assisted-by: Claude Opus 4.6 (1M context) noreply@anthropic.com

Previously, socketOnDrain could be invoked synchronously from
_flushOutput (via _onPendingData -> updateOutgoingData) while the bytes
just handed to the socket were still buffered and while outputSize had
not yet been reset on the OutgoingMessage. The 'drain' event fired even
though res.writableLength was non-zero, breaking the invariant a user
would reasonably expect after `while (!res.write(...));`.

Gate the emission in socketOnDrain on msg.writableLength === 0 (which
also covers outputSize + chunked buffer + socket.writableLength), and
apply the same check in OutgoingMessage._flush so that 'drain' is only
emitted when the response is genuinely drained. The socket's own
'drain' event will otherwise propagate through socketOnDrain when the
socket buffer actually empties.

Signed-off-by: Robert Nagy <ronagy@icloud.com>
Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ronag ronag requested a review from mcollina April 24, 2026 18:34
@ronag ronag self-assigned this Apr 24, 2026
@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

nodejs-github-bot commented Apr 24, 2026

Review requested:

  • @nodejs/http
  • @nodejs/net

@nodejs-github-bot nodejs-github-bot added http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. labels Apr 24, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.65%. Comparing base (bcdf2e0) to head (d6a90b7).
⚠️ Report is 847 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #62936      +/-   ##
==========================================
+ Coverage   88.53%   89.65%   +1.12%     
==========================================
  Files         704      706       +2     
  Lines      208759   219226   +10467     
  Branches    40281    42004    +1723     
==========================================
+ Hits       184816   196547   +11731     
+ Misses      15947    14591    -1356     
- Partials     7996     8088      +92     
Files with missing lines Coverage Δ
lib/_http_outgoing.js 96.13% <100.00%> (+0.44%) ⬆️
lib/_http_server.js 97.29% <100.00%> (+0.39%) ⬆️

... and 414 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants